// Magic Software, Inc.
// http://www.magic-software.com
// Copyright (c) 2000, All Rights Reserved
//
// Source code from Magic Software is supplied under the terms of a license
// agreement and may not be copied or disclosed except in accordance with the
// terms of that agreement.  The various license agreements may be found at
// the Magic Software web site.  This file is subject to the license
//
// FREE SOURCE CODE
// http://www.magic-software.com/License/free.pdf

#include "MgcEuler.h"

//---------------------------------------------------------------------------
MgcEuler::MgcEuler (int iDim, MgcReal fStep, Function* aoF)
    :
    MgcODE(iDim,fStep,aoF)
{
}
//---------------------------------------------------------------------------
MgcEuler::MgcEuler (int iDim, MgcReal fStep, AutoFunction* aoA)
    :
    MgcODE(iDim,fStep,aoA)
{
}
//---------------------------------------------------------------------------
void MgcEuler::Update (MgcReal fTIn, MgcReal* afXIn, MgcReal& rfTOut,
    MgcReal* afXOut)
{
    for (int i = 0; i < m_iDim; i++)
        afXOut[i] = afXIn[i] + m_fStep*m_aoF[i](fTIn,afXIn);

    rfTOut = fTIn + m_fStep;
}
//---------------------------------------------------------------------------
void MgcEuler::Update (MgcReal* afXIn, MgcReal* afXOut)
{
    for (int i = 0; i < m_iDim; i++)
        afXOut[i] = afXIn[i] + m_fStep*m_aoA[i](afXIn);
}
//---------------------------------------------------------------------------
void MgcEuler::SetStepSize (MgcReal fStep)
{
    m_fStep = fStep;
}
//---------------------------------------------------------------------------

#ifdef EULER_TEST

#include "MgcRTLib.h"

MgcReal F0 (MgcReal fT, MgcReal* afX) { return afX[0]*afX[0]; }
MgcReal F1 (MgcReal fT, MgcReal* afX) { return -2.0*afX[0]*afX[1]; }

int main ()
{
    const int iDim = 2;
    const MgcReal fStep = 0.001;
    MgcODE::Function aoF[2] = { F0, F1 };

    MgcEuler kODE(iDim,fStep,aoF);
    MgcReal fTIn = 0.0, fTOut;
    MgcReal afXIn[iDim] = { 1.0, 1.0 }, afXOut[iDim];

    for (int i = 0; i < 10; i++)
    {
        cout << "t = " << fTIn << ' ';
        cout << "x = " << afXIn[0] << ' ';
        cout << "y = " << afXIn[1] << endl;
        kODE.Update(fTIn,afXIn,fTOut,afXOut);
        for (int j = 0; j < iDim; j++)
            afXIn[j] = afXOut[j];
        fTIn = fTOut;
    }

    // t = 0 x = 1 y = 1
    // t = 0.001 x = 1.001 y = 0.998
    // t = 0.002 x = 1.002 y = 0.996002
    // t = 0.003 x = 1.00301 y = 0.994006
    // t = 0.004 x = 1.00401 y = 0.992012
    // t = 0.005 x = 1.00502 y = 0.99002
    // t = 0.006 x = 1.00603 y = 0.98803
    // t = 0.007 x = 1.00704 y = 0.986042
    // t = 0.008 x = 1.00806 y = 0.984056
    // t = 0.009 x = 1.00907 y = 0.982072

    return 0;
}

#endif
